home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / dev / c / libiconv_src.lha / src / iso2022_jp2.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-07  |  12.2 KB  |  507 lines

  1.  
  2. /*
  3.  * ISO-2022-JP-2
  4.  */
  5.  
  6. /* Specification: RFC 1554 */
  7. /* ESC '(' 'I' for JISX0201 Katakana is an extension not found in RFC 1554 or
  8.    CJK.INF, but implemented in glibc-2.1 and qt-2.0. */
  9.  
  10. #define ESC 0x1b
  11.  
  12. /*
  13.  * The state is composed of one of the following values
  14.  */
  15. #define STATE_ASCII             0
  16. #define STATE_JISX0201ROMAN     1
  17. #define STATE_JISX0201KATAKANA  2
  18. #define STATE_JISX0208          3
  19. #define STATE_JISX0212          4
  20. #define STATE_GB2312            5
  21. #define STATE_KSC5601           6
  22. /*
  23.  * and one of the following values, << 8
  24.  */
  25. #define STATE_G2_NONE           0
  26. #define STATE_G2_ISO8859_1      1
  27. #define STATE_G2_ISO8859_7      2
  28.  
  29. #define SPLIT_STATE \
  30.   unsigned int state1 = state & 0xff, state2 = state >> 8
  31. #define COMBINE_STATE \
  32.   state = (state2 << 8) | state1
  33.  
  34. static int
  35. iso2022_jp2_mbtowc (conv_t conv, wchar_t *pwc, const unsigned char *s, int n)
  36. {
  37.   state_t state = conv->istate;
  38.   SPLIT_STATE;
  39.   int count = 0;
  40.   unsigned char c;
  41.   for (;;) {
  42.     c = *s;
  43.     if (c == ESC) {
  44.       if (n < count+3)
  45.         goto none;
  46.       if (s[1] == '(') {
  47.         if (s[2] == 'B') {
  48.           state1 = STATE_ASCII;
  49.           s += 3; count += 3;
  50.           if (n < count+1)
  51.             goto none;
  52.           continue;
  53.         }
  54.         if (s[2] == 'J') {
  55.           state1 = STATE_JISX0201ROMAN;
  56.           s += 3; count += 3;
  57.           if (n < count+1)
  58.             goto none;
  59.           continue;
  60.         }
  61.         if (s[2] == 'I') {
  62.           state1 = STATE_JISX0201KATAKANA;
  63.           s += 3; count += 3;
  64.           if (n < count+1)
  65.             goto none;
  66.           continue;
  67.         }
  68.         return RET_ILSEQ;
  69.       }
  70.       if (s[1] == '$') {
  71.         if (s[2] == '@' || s[2] == 'B') {
  72.           /* We don't distinguish JIS X 0208-1978 and JIS X 0208-1983. */
  73.           state1 = STATE_JISX0208;
  74.           s += 3; count += 3;
  75.           if (n < count+1)
  76.             goto none;
  77.           continue;
  78.         }
  79.         if (s[2] == 'A') {
  80.           state1 = STATE_GB2312;
  81.           s += 3; count += 3;
  82.           if (n < count+1)
  83.             goto none;
  84.           continue;
  85.         }
  86.         if (s[2] == '(') {
  87.           if (n < count+4)
  88.             goto none;
  89.           if (s[3] == 'D') {
  90.             state1 = STATE_JISX0212;
  91.             s += 4; count += 4;
  92.             if (n < count+1)
  93.               goto none;
  94.             continue;
  95.           }
  96.           if (s[3] == 'C') {
  97.             state1 = STATE_KSC5601;
  98.             s += 4; count += 4;
  99.             if (n < count+1)
  100.               goto none;
  101.             continue;
  102.           }
  103.           return RET_ILSEQ;
  104.         }
  105.         return RET_ILSEQ;
  106.       }
  107.       if (s[1] == '.') {
  108.         if (n < count+3)
  109.           goto none;
  110.         if (s[2] == 'A') {
  111.           state2 = STATE_G2_ISO8859_1;
  112.           s += 3; count += 3;
  113.           if (n < count+1)
  114.             goto none;
  115.           continue;
  116.         }
  117.         if (s[2] == 'F') {
  118.           state2 = STATE_G2_ISO8859_7;
  119.           s += 3; count += 3;
  120.           if (n < count+1)
  121.             goto none;
  122.           continue;
  123.         }
  124.         return RET_ILSEQ;
  125.       }
  126.       if (s[1] == 'N') {
  127.         switch (state2) {
  128.           case STATE_G2_NONE:
  129.             return RET_ILSEQ;
  130.           case STATE_G2_ISO8859_1:
  131.             if (s[2] < 0x80) {
  132.               unsigned char buf = s[2]+0x80;
  133.               int ret = iso8859_1_mbtowc(conv,pwc,&buf,1);
  134.               if (ret == RET_ILSEQ)
  135.                 return RET_ILSEQ;
  136.               if (ret != 1) abort();
  137.               COMBINE_STATE;
  138.               conv->istate = state;
  139.               return count+3;
  140.             } else
  141.               return RET_ILSEQ;
  142.           case STATE_G2_ISO8859_7:
  143.             if (s[2] < 0x80) {
  144.               unsigned char buf = s[2]+0x80;
  145.               int ret = iso8859_7_mbtowc(conv,pwc,&buf,1);
  146.               if (ret == RET_ILSEQ)
  147.                 return RET_ILSEQ;
  148.               if (ret != 1) abort();
  149.               COMBINE_STATE;
  150.               conv->istate = state;
  151.               return count+3;
  152.             } else
  153.               return RET_ILSEQ;
  154.           default: abort();
  155.         }
  156.       }
  157.       return RET_ILSEQ;
  158.     }
  159.     break;
  160.   }
  161.   switch (state1) {
  162.     case STATE_ASCII:
  163.       if (c < 0x80) {
  164.         int ret = ascii_mbtowc(conv,pwc,s,1);
  165.         if (ret == RET_ILSEQ)
  166.           return RET_ILSEQ;
  167.         if (ret != 1) abort();
  168.         if (*pwc == 0x000a || *pwc == 0x000d)
  169.           state2 = STATE_G2_NONE;
  170.         COMBINE_STATE;
  171.         conv->istate = state;
  172.         return count+1;
  173.       } else
  174.         return RET_ILSEQ;
  175.     case STATE_JISX0201ROMAN:
  176.       if (c < 0x80) {
  177.         int ret = jisx0201_mbtowc(conv,pwc,s,1);
  178.         if (ret == RET_ILSEQ)
  179.           return RET_ILSEQ;
  180.         if (ret != 1) abort();
  181.         if (*pwc == 0x000a || *pwc == 0x000d)
  182.           state2 = STATE_G2_NONE;
  183.         COMBINE_STATE;
  184.         conv->istate = state;
  185.         return count+1;
  186.       } else
  187.         return RET_ILSEQ;
  188.     case STATE_JISX0201KATAKANA:
  189.       if (c < 0x80) {
  190.         unsigned char buf = c+0x80;
  191.         int ret = jisx0201_mbtowc(conv,pwc,&buf,1);
  192.         if (ret == RET_ILSEQ)
  193.           return RET_ILSEQ;
  194.         if (ret != 1) abort();
  195.         COMBINE_STATE;
  196.         conv->istate = state;
  197.         return count+1;
  198.       } else
  199.         return RET_ILSEQ;
  200.     case STATE_JISX0208:
  201.       if (n < count+2)
  202.         goto none;
  203.       if (s[0] < 0x80 && s[1] < 0x80) {
  204.         int ret = jisx0208_mbtowc(conv,pwc,s,2);
  205.         if (ret == RET_ILSEQ)
  206.           return RET_ILSEQ;
  207.         if (ret != 2) abort();
  208.         COMBINE_STATE;
  209.         conv->istate = state;
  210.         return count+2;
  211.       } else
  212.         return RET_ILSEQ;
  213.     case STATE_JISX0212:
  214.       if (n < count+2)
  215.         goto none;
  216.       if (s[0] < 0x80 && s[1] < 0x80) {
  217.         int ret = jisx0212_mbtowc(conv,pwc,s,2);
  218.         if (ret == RET_ILSEQ)
  219.           return RET_ILSEQ;
  220.         if (ret != 2) abort();
  221.         COMBINE_STATE;
  222.         conv->istate = state;
  223.         return count+2;
  224.       } else
  225.         return RET_ILSEQ;
  226.     case STATE_GB2312:
  227.       if (n < count+2)
  228.         goto none;
  229.       if (s[0] < 0x80 && s[1] < 0x80) {
  230.         int ret = gb2312_mbtowc(conv,pwc,s,2);
  231.         if (ret == RET_ILSEQ)
  232.           return RET_ILSEQ;
  233.         if (ret != 2) abort();
  234.         COMBINE_STATE;
  235.         conv->istate = state;
  236.         return count+2;
  237.       } else
  238.         return RET_ILSEQ;
  239.     case STATE_KSC5601:
  240.       if (n < count+2)
  241.         goto none;
  242.       if (s[0] < 0x80 && s[1] < 0x80) {
  243.         int ret = ksc5601_mbtowc(conv,pwc,s,2);
  244.         if (ret == RET_ILSEQ)
  245.           return RET_ILSEQ;
  246.         if (ret != 2) abort();
  247.         COMBINE_STATE;
  248.         conv->istate = state;
  249.         return count+2;
  250.       } else
  251.         return RET_ILSEQ;
  252.     default: abort();
  253.   }
  254.  
  255. none:
  256.   COMBINE_STATE;
  257.   conv->istate = state;
  258.   return RET_TOOFEW(count);
  259. }
  260.  
  261. static int
  262. iso2022_jp2_wctomb (conv_t conv, unsigned char *r, wchar_t wc, int n)
  263. {
  264.   state_t state = conv->ostate;
  265.   SPLIT_STATE;
  266.   unsigned char buf[2];
  267.   int ret;
  268.  
  269.   /* Try ASCII. */
  270.   ret = ascii_wctomb(conv,buf,wc,1);
  271.   if (ret != RET_ILSEQ) {
  272.     if (ret != 1) abort();
  273.     if (buf[0] < 0x80) {
  274.       int count = (state1 == STATE_ASCII ? 1 : 4);
  275.       if (n < count)
  276.         return RET_TOOSMALL;
  277.       if (state1 != STATE_ASCII) {
  278.         r[0] = ESC;
  279.         r[1] = '(';
  280.         r[2] = 'B';
  281.         r += 3;
  282.         state1 = STATE_ASCII;
  283.       }
  284.       r[0] = buf[0];
  285.       if (wc == 0x000a || wc == 0x000d)
  286.         state2 = STATE_G2_NONE;
  287.       COMBINE_STATE;
  288.       conv->ostate = state;
  289.       return count;
  290.     }
  291.   }
  292.  
  293.   /* Try ISO-8859-1. */
  294.   ret = iso8859_1_wctomb(conv,buf,wc,1);
  295.   if (ret != RET_ILSEQ) {
  296.     if (ret != 1) abort();
  297.     if (buf[0] >= 0x80) {
  298.       int count = (state2 == STATE_G2_ISO8859_1 ? 3 : 6);
  299.       if (n < count)
  300.         return RET_TOOSMALL;
  301.       if (state2 != STATE_G2_ISO8859_1) {
  302.         r[0] = ESC;
  303.         r[1] = '.';
  304.         r[2] = 'A';
  305.         r += 3;
  306.         state2 = STATE_G2_ISO8859_1;
  307.       }
  308.       r[0] = ESC;
  309.       r[1] = 'N';
  310.       r[2] = buf[0]-0x80;
  311.       COMBINE_STATE;
  312.       conv->ostate = state;
  313.       return count;
  314.     }
  315.   }
  316.  
  317.   /* Try ISO-8859-7. */
  318.   ret = iso8859_7_wctomb(conv,buf,wc,1);
  319.   if (ret != RET_ILSEQ) {
  320.     if (ret != 1) abort();
  321.     if (buf[0] >= 0x80) {
  322.       int count = (state2 == STATE_G2_ISO8859_7 ? 3 : 6);
  323.       if (n < count)
  324.         return RET_TOOSMALL;
  325.       if (state2 != STATE_G2_ISO8859_7) {
  326.         r[0] = ESC;
  327.         r[1] = '.';
  328.         r[2] = 'F';
  329.         r += 3;
  330.         state2 = STATE_G2_ISO8859_7;
  331.       }
  332.       r[0] = ESC;
  333.       r[1] = 'N';
  334.       r[2] = buf[0]-0x80;
  335.       COMBINE_STATE;
  336.       conv->ostate = state;
  337.       return count;
  338.     }
  339.   }
  340.  
  341.   /* Try JIS X 0201-1976 Roman and Kana. */
  342.   ret = jisx0201_wctomb(conv,buf,wc,1);
  343.   if (ret != RET_ILSEQ) {
  344.     if (ret != 1) abort();
  345.     if (buf[0] < 0x80) {
  346.       int count = (state1 == STATE_JISX0201ROMAN ? 1 : 4);
  347.       if (n < count)
  348.         return RET_TOOSMALL;
  349.       if (state1 != STATE_JISX0201ROMAN) {
  350.         r[0] = ESC;
  351.         r[1] = '(';
  352.         r[2] = 'J';
  353.         r += 3;
  354.         state1 = STATE_JISX0201ROMAN;
  355.       }
  356.       r[0] = buf[0];
  357.       if (wc == 0x000a || wc == 0x000d)
  358.         state2 = STATE_G2_NONE;
  359.       COMBINE_STATE;
  360.       conv->ostate = state;
  361.       return count;
  362.     } else {
  363.       int count = (state1 == STATE_JISX0201KATAKANA ? 1 : 4);
  364.       if (n < count)
  365.         return RET_TOOSMALL;
  366.       if (state1 != STATE_JISX0201KATAKANA) {
  367.         r[0] = ESC;
  368.         r[1] = '(';
  369.         r[2] = 'I';
  370.         r += 3;
  371.         state1 = STATE_JISX0201KATAKANA;
  372.       }
  373.       r[0] = buf[0]-0x80;
  374.       COMBINE_STATE;
  375.       conv->ostate = state;
  376.       return count;
  377.     }
  378.   }
  379.  
  380.   /* Try JIS X 0208-1990 in place of JIS X 0208-1978 and JIS X 0208-1983. */
  381.   ret = jisx0208_wctomb(conv,buf,wc,2);
  382.   if (ret != RET_ILSEQ) {
  383.     if (ret != 2) abort();
  384.     if (buf[0] < 0x80 && buf[1] < 0x80) {
  385.       int count = (state1 == STATE_JISX0208 ? 2 : 5);
  386.       if (n < count)
  387.         return RET_TOOSMALL;
  388.       if (state1 != STATE_JISX0208) {
  389.         r[0] = ESC;
  390.         r[1] = '$';
  391.         r[2] = 'B';
  392.         r += 3;
  393.         state1 = STATE_JISX0208;
  394.       }
  395.       r[0] = buf[0];
  396.       r[1] = buf[1];
  397.       COMBINE_STATE;
  398.       conv->ostate = state;
  399.       return count;
  400.     }
  401.   }
  402.  
  403.   /* Try JIS X 0212-1990. */
  404.   ret = jisx0212_wctomb(conv,buf,wc,2);
  405.   if (ret != RET_ILSEQ) {
  406.     if (ret != 2) abort();
  407.     if (buf[0] < 0x80 && buf[1] < 0x80) {
  408.       int count = (state1 == STATE_JISX0212 ? 2 : 6);
  409.       if (n < count)
  410.         return RET_TOOSMALL;
  411.       if (state1 != STATE_JISX0212) {
  412.         r[0] = ESC;
  413.         r[1] = '$';
  414.         r[2] = '(';
  415.         r[3] = 'D';
  416.         r += 4;
  417.         state1 = STATE_JISX0212;
  418.       }
  419.       r[0] = buf[0];
  420.       r[1] = buf[1];
  421.       COMBINE_STATE;
  422.       conv->ostate = state;
  423.       return count;
  424.     }
  425.   }
  426.  
  427.   /* Try GB 2312-1980. */
  428.   ret = gb2312_wctomb(conv,buf,wc,2);
  429.   if (ret != RET_ILSEQ) {
  430.     if (ret != 2) abort();
  431.     if (buf[0] < 0x80 && buf[1] < 0x80) {
  432.       int count = (state1 == STATE_GB2312 ? 2 : 5);
  433.       if (n < count)
  434.         return RET_TOOSMALL;
  435.       if (state1 != STATE_GB2312) {
  436.         r[0] = ESC;
  437.         r[1] = '$';
  438.         r[2] = 'A';
  439.         r += 3;
  440.         state1 = STATE_GB2312;
  441.       }
  442.       r[0] = buf[0];
  443.       r[1] = buf[1];
  444.       COMBINE_STATE;
  445.       conv->ostate = state;
  446.       return count;
  447.     }
  448.   }
  449.  
  450.   /* Try KS C 5601-1992. */
  451.   ret = ksc5601_wctomb(conv,buf,wc,2);
  452.   if (ret != RET_ILSEQ) {
  453.     if (ret != 2) abort();
  454.     if (buf[0] < 0x80 && buf[1] < 0x80) {
  455.       int count = (state1 == STATE_KSC5601 ? 2 : 6);
  456.       if (n < count)
  457.         return RET_TOOSMALL;
  458.       if (state1 != STATE_KSC5601) {
  459.         r[0] = ESC;
  460.         r[1] = '$';
  461.         r[2] = '(';
  462.         r[3] = 'C';
  463.         r += 4;
  464.         state1 = STATE_KSC5601;
  465.       }
  466.       r[0] = buf[0];
  467.       r[1] = buf[1];
  468.       COMBINE_STATE;
  469.       conv->ostate = state;
  470.       return count;
  471.     }
  472.   }
  473.  
  474.   return RET_ILSEQ;
  475. }
  476.  
  477. static int
  478. iso2022_jp2_reset (conv_t conv, unsigned char *r, int n)
  479. {
  480.   state_t state = conv->ostate;
  481.   SPLIT_STATE;
  482.   (void)state2;
  483.   if (state1 != STATE_ASCII) {
  484.     if (n < 3)
  485.       return RET_TOOSMALL;
  486.     r[0] = ESC;
  487.     r[1] = '(';
  488.     r[2] = 'B';
  489.     /* conv->ostate = 0; will be done by the caller */
  490.     return 3;
  491.   } else
  492.     return 0;
  493. }
  494.  
  495. #undef COMBINE_STATE
  496. #undef SPLIT_STATE
  497. #undef STATE_G2_ISO8859_7
  498. #undef STATE_G2_ISO8859_1
  499. #undef STATE_G2_NONE
  500. #undef STATE_KSC5601
  501. #undef STATE_GB2312
  502. #undef STATE_JISX0212
  503. #undef STATE_JISX0208
  504. #undef STATE_JISX0201KATAKANA
  505. #undef STATE_JISX0201ROMAN
  506. #undef STATE_ASCII
  507.